package com.douyang.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.douyang.VO.GetLivePeople;
import com.douyang.VO.VideoUserInfoVO;
import com.douyang.base.model.UserBaseInfo;
import com.douyang.base.utils.UserUtil;
import com.douyang.handle.WebSocketServer;
import com.douyang.mapper.UserVideoLikedMapper;
import com.douyang.pojo.UserFollowed;
import com.douyang.pojo.UserVideoLiked;
import com.douyang.service.UserBaseInfoService;
import com.douyang.service.UserFollowedService;
import com.douyang.service.UserVideoLikedService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xiaoma
 * @since 2025-03-05
 */
@Service
public class UserVideoLikedServiceImpl extends ServiceImpl<UserVideoLikedMapper, UserVideoLiked> implements UserVideoLikedService {
    @Autowired
    private UserBaseInfoService userBaseInfoService;

    @Autowired
    private UserFollowedService userFollowedService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public VideoUserInfoVO getVideoUserInfo(Long authorId, Long videoId) {
        boolean login = StpUtil.isLogin();
        VideoUserInfoVO videoUserInfoVO = new VideoUserInfoVO();
        UserBaseInfo userBaseInfo = userBaseInfoService.getById(authorId);
        videoUserInfoVO.setAvatar(userBaseInfo.getAvatar());
        if (login) {
            UserBaseInfo loginUserBaseInfo = UserUtil.getLoginUserBaseInfo();

            if (loginUserBaseInfo.getId().equals(authorId)) {
                videoUserInfoVO.setFollowed(true);
            } else {
                videoUserInfoVO.setFollowed(
                        userFollowedService.lambdaQuery()
                                .eq(UserFollowed::getUserId, loginUserBaseInfo.getId())
                                .eq(UserFollowed::getFollowedUserId, authorId)
                                .exists()
                );

            }
            videoUserInfoVO.setLiked(
                    lambdaQuery()
                            .eq(UserVideoLiked::getUserId, loginUserBaseInfo.getId())
                            .eq(UserVideoLiked::getVideoId, videoId)
                            .exists()
            );
        } else {
            videoUserInfoVO.setFollowed(false);
            videoUserInfoVO.setLiked(false);
        }


        videoUserInfoVO.setLogin(login);
        videoUserInfoVO.setLikeCount(
                getVideoLikeCount(videoId)
        );

        return videoUserInfoVO;
    }

    @Override
    public Integer getVideoLikeCount(Long videoId) {
        return Math.toIntExact(lambdaQuery().eq(UserVideoLiked::getVideoId, videoId).count());
    }

    @Override
    public void loveVideo(Long videoId) {
        UserBaseInfo loginUserBaseInfo = UserUtil.getLoginUserBaseInfo();
        boolean exists = lambdaQuery()
                .eq(UserVideoLiked::getVideoId, videoId)
                .eq(UserVideoLiked::getUserId, loginUserBaseInfo.getId())
                .exists();
        if (exists) return;

        UserVideoLiked userVideoLiked = UserVideoLiked.builder()
                .userId(loginUserBaseInfo.getId())
                .videoId(videoId)
                .build();

        save(userVideoLiked);
    }

    @Override
    public void unLoveVideo(Long videoId) {
        UserBaseInfo loginUserBaseInfo = UserUtil.getLoginUserBaseInfo();
        remove(new QueryWrapper<UserVideoLiked>()
                .eq("user_id", loginUserBaseInfo.getId())
                .eq("video_id", videoId)
        );
    }

    @Override
    public List<Long> getUserLikedVideoIds(Long userId) {
        return lambdaQuery()
                .select(UserVideoLiked::getVideoId)
                .eq(UserVideoLiked::getUserId, userId)
                .list()
                .stream()
                .map(UserVideoLiked::getVideoId)
                .toList();
    }

    @Override
    public void liveLike(Long liveId) {
        UserBaseInfo loginUserBaseInfo = UserUtil.getLoginUserBaseInfo();
        stringRedisTemplate.opsForZSet().incrementScore(liveId.toString(), loginUserBaseInfo.getId().toString(), 1);
        webSocketServer.sendToAllClient(null,liveId,loginUserBaseInfo.getId(),null,4);
    }

    @Override
    public List<GetLivePeople> getLivePeopleList(Long liveId) {
        Set<Long> userIdSet = webSocketServer.getUserIdSet(liveId);

        if (userIdSet.isEmpty()) return List.of();
        return userIdSet.stream().map(userid -> {
            UserBaseInfo userBaseInfo = userBaseInfoService.getById(userid);
            if (userBaseInfo == null) {
                return null;
            }

            Double score = stringRedisTemplate.opsForZSet().score(liveId.toString(), userid.toString());
            if (score == null) score=0.0;
            return GetLivePeople.builder()
                    .userId(userid)
                    .avatar(userBaseInfo.getAvatar())
                    .userName(userBaseInfo.getUserName())
                    .likeCount((long) score.intValue())
                    .build();
        }).sorted((v1,v2)->{
            assert v1 != null;
            return Math.toIntExact(v2.getLikeCount() - v1.getLikeCount());}).toList();
    }
}
